﻿
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.CodeDom.Compiler;

using Ionic.Zlib;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SWF
{
    public class DefineBitsTag : ISwfTag
    {
        private TagType tagType = TagType.DefineBits;
        public TagType TagType { get { return tagType; } }

        public UInt16 CharacterId;
        public byte[] JpegData;
        public bool HasOwnTable = false;
        public bool HasAlphaData = false;
        public byte[] CompressedAlphaData;

        // this needs to combine with the jpegTables in the swfCompilationUnit to make an image
        public DefineBitsTag(SwfReader r, uint curTagLen, bool hasOwnTable, bool hasAlphaData)
        {
            this.HasOwnTable = hasOwnTable;
            this.HasAlphaData = hasAlphaData;

            if (hasOwnTable && !hasAlphaData)
            {
                tagType = TagType.DefineBitsJPEG2;
            }
            else if (hasOwnTable && hasAlphaData)
            {
                tagType = TagType.DefineBitsJPEG3;
            }

            CharacterId = r.GetUI16();
            if (!hasAlphaData)
            {
                if (!hasOwnTable)
                {
                    r.GetBytes(2); // SOI
                    JpegData = r.GetBytes(curTagLen - 6);
                    r.GetBytes(2); // EOI
                }
                else
                {
                    JpegData = r.GetBytes(curTagLen - 2);
                    CleanData();
                }
            }
            else
            {
                uint jpgDataSize = r.GetUI32();
                JpegData = r.GetBytes(jpgDataSize);

                // ignore alpha for now
                CompressedAlphaData = r.GetBytes(curTagLen - 6 - jpgDataSize);
                CleanData();
            }
        }

        public Texture2D GenerateTexture2D()
        {
            MemoryStream lStream = new MemoryStream(JpegData);
            Texture2D lTexture = Texture2D.FromStream(SWFMain.Device, lStream);

            if (HasAlphaData)
            {
                int lSize = lTexture.Width * lTexture.Height;
                Color[] lData = new Color[lSize];
                lTexture.GetData<Color>(lData);

                byte[] lDecompressedBytes = lDecompressedBytes = ZlibStream.UncompressBuffer(CompressedAlphaData);
                for (int lCount = 0; lCount < lSize; ++lCount)
                {
                    lData[lCount].A = lDecompressedBytes[lCount];
                }
                lTexture.SetData<Color>(lData);
            }

            return lTexture;
#if FALSE
            //  PNG (SWF 8+)
            if (JpegData[0] == 0x89 && JpegData[1] == 0x50 && JpegData[2] == 0x4E && JpegData[3] == 0x47
                && JpegData[4] == 0x0D && JpegData[5] == 0x0A && JpegData[6] == 0x1A && JpegData[7] == 0x0A)
            {

            }
            //  GIF89a (SWF 8+)
            else if (JpegData[0] == 0x47 && JpegData[1] == 0x49 && JpegData[2] == 0x46 && JpegData[3] == 0x38
                && JpegData[4] == 0x39 && JpegData[5] == 0x61)
            {

            }
            //  JPEG
            else
            {
                byte[][] lBuffer = new byte[1024][];
                for (int lCount = 0; lCount < 1024; ++lCount)
                {
                    lBuffer[lCount] = new byte[1024];
                }

                jpeg_decompress_struct cinfo = new jpeg_decompress_struct();
                cinfo.jpeg_stdio_src(lStream);
                cinfo.jpeg_read_header(true);
                cinfo.jpeg_start_decompress();
                while (cinfo.Output_scanline < cinfo.Output_height)
                {
                    int num_scanlines = cinfo.jpeg_read_scanlines(lBuffer, 1024);
                    //dest_mgr.put_pixel_rows(num_scanlines);
                }
                cinfo.jpeg_finish_decompress();
            }
#endif
        }

        private void CleanData()
        {
            // first header
            if (JpegData[0] == 0xFF && JpegData[1] == 0xD9 && JpegData[2] == 0xFF && JpegData[3] == 0xD8)
            {
                byte[] copy = new byte[JpegData.Length - 4];
                Array.Copy(JpegData, 4, copy, 0, JpegData.Length - 4);
                JpegData = copy;
            }
            // cleans out bug markers in swf jpgs
            int index = 2;
            int len = this.JpegData.Length;
            while (index + 3 < len)
            {
                byte b0 = JpegData[index];
                if (b0 != 0xFF)
                {
                    break;
                }
                if (JpegData[index + 1] == 0xD9 && JpegData[index + 2] == 0xFF && JpegData[index + 3] == 0xD8)
                {
                    // bingo
                    byte[] copy = new byte[JpegData.Length - 4];
                    Array.Copy(JpegData, 0, copy, 0, index);
                    Array.Copy(JpegData, index + 4, copy, index, JpegData.Length - index - 4);
                    JpegData = copy;
                    break;
                }
                else
                {
                    int tagLen = (JpegData[index + 2] << 8) + JpegData[index + 3] + 2;
                    index += tagLen;
                }
            }
        }
    }
}
